﻿using Microsoft.Extensions.Diagnostics.HealthChecks;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Threading.Tasks;
using System.Threading;
using System.Linq;
using System;
using xBei.Redis.Extension;

namespace net.xBei.WebApi.Repository {
    /// <summary>
    /// 
    /// </summary>
    public class ReadyHealthCheck : IHealthCheck {
        private readonly IServiceProvider serviceProvider;

        static readonly ConcurrentDictionary<string, Func<IServiceProvider,Task<bool>>> CheckList = new();
        //public void SetReady(string key, bool isReady = true) {
        //    CheckList.AddOrUpdate(key, isReady, (k, ov) => isReady);
        //    //CheckList[key] = isReady;
        //}
        //public static void ReadyIt(string key) {
        //    if (CheckList.IsEmpty) { return; }
        //    CheckList.AddOrUpdate(key, true, (k, ov) => true);
        //    //CheckList[key] = isReady;
        //}
        /// <summary>
        /// 
        /// </summary>
        /// <param name="serviceProvider"></param>
        public ReadyHealthCheck(IServiceProvider serviceProvider) {
            this.serviceProvider = serviceProvider;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="check"></param>
        public static void AddCheckList(string key, Func<IServiceProvider, Task<bool>> check) {
            CheckList.AddOrUpdate(key, check, (k, ov) => check);
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="context"></param>
        /// <param name="cancellationToken"></param>
        /// <returns></returns>
        public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) {
            //var isHealthy = false;//CheckList.Count == CheckList.Values.Count(v => v);
            foreach (var k in CheckList) {
                var check = k.Value;
                if (!await check.Invoke(serviceProvider)) {
                    return HealthCheckResult.Unhealthy("An unhealthy result.");
                }
            }
            return HealthCheckResult.Healthy("A healthy result.");
        }
    }
    /// <summary>
    /// Redis健康监测
    /// </summary>
    public class RedisHealthCheck : IHealthCheck {
        private readonly RedisClient redisClient;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="redisClient"></param>
        public RedisHealthCheck(RedisClient redisClient) {
            this.redisClient = redisClient;
        }
        /// <inheritdoc/>
        public async Task<HealthCheckResult> CheckHealthAsync(HealthCheckContext context, CancellationToken cancellationToken = default) {
                var db = redisClient.Database;
            try {
                var x = await db.PingAsync();
                if (x.TotalSeconds > 60) {
                    return HealthCheckResult.Unhealthy("An unhealthy result.");
                }
            } catch {
                return HealthCheckResult.Unhealthy("An unhealthy result.");
            }
            return HealthCheckResult.Healthy("A healthy result.");
        }
    }
}
